package com.gitee.wsl.mathematics.function

import kotlin.math.pow

/**
 * Base for decimal numbers.
 */
private const val DECIMAL = 10

/**
 * Functional interface representing a narcissistic number check.
 */
fun interface NarcissisticNumber {
    /**
     * Checks whether the given number is an Armstrong number.
     *
     * @param number The number to check.
     * @return `true` if the number is an Armstrong number, `false` otherwise.
     */
    fun isArmstrong(number: Int): Boolean
}

/**
 * Implementation of the NarcissisticNumber interface.
 */
data object NarcissisticNumberImpl : NarcissisticNumber {
    /**
     * Checks whether the given number is an Armstrong number.
     *
     * @param number The number to check.
     * @return `true` if the number is an Armstrong number, `false` otherwise.
     */
    override fun isArmstrong(number: Int): Boolean {
        if (number < 0) {
            return false
        }
        var sum = 0
        var temp = number
        val totalDigits = numberOfDigits(number)
        while (temp > 0) {
            val rem = temp % DECIMAL
            sum += rem.toDouble().pow(totalDigits.toDouble()).toInt()
            temp /= DECIMAL
        }
        return number == sum
    }

    /**
     * Calculates the number of digits in the given number.
     *
     * @param num The number to calculate the number of digits for.
     * @return The number of digits in the given number.
     */
    private fun numberOfDigits(num: Int): Int {
        var res = num
        var totalDigits = 0
        while (res > 0) {
            res /= DECIMAL
            totalDigits++
        }
        return totalDigits
    }
}
